﻿//        Another Demo from Andy L. & MissedMemo.com
// Borrow whatever code seems useful - just don't try to hold
// me responsible for any ill effects. My demos sometimes use
// licensed images which CANNOT legally be copied and reused.

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections.Specialized;


namespace MissedMemo.MeatAndCheeseDisc.BusinessLogic
{
    public class Order : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private int _nowServingNumber = NowServingNumberGenerator.Next();

        private Customer _customer = new Customer();

        private DateTime _datetimeOrderPlaced;
        private TimeSpan _elapsedTimeProcessing; 

        private ObservableCollection<Pizza> _orderItems = new ObservableCollection<Pizza>();
        
        private double _cost;
        private double _tax;
        private double _taxRate = PriceLookerUpper.TaxRate();
        private double _totalCost;

        private bool _deliveryRequested;
        private bool _hasUnsavedChanges;


    #region Properties...

        public bool UnsavedChanges
        {
            get { return _hasUnsavedChanges; }
            set
            {
                _hasUnsavedChanges = value;
                Notify( "UnsavedChanges" );
            }
        }

        public bool DeliveryRequested
        {
            get { return _deliveryRequested; }
            set
            {
                _deliveryRequested = value;
                UnsavedChanges = true;
                Notify( "DeliveryRequested" );
            }
        }

        public int NowServingNumber
        {
            get { return _nowServingNumber; }
            set
            {
                _nowServingNumber = value;
            }
        }

        public Customer Customer
        {
            get { return _customer; }
            set
            {
                _customer = value;
            }
        }

        public DateTime DateTimeOrderPlaced
        {
            get { return _datetimeOrderPlaced; }
            set
            {
                _datetimeOrderPlaced = value;
            }
        }

        public TimeSpan ElapsedTime
        {
            get { return _elapsedTimeProcessing; }
            set
            {
                _elapsedTimeProcessing = value;
                Notify( "ElapsedTime" );
            }
        }

        public ObservableCollection<Pizza> OrderItems
        {
            get { return _orderItems; }
            set
            {
                _orderItems = value;
            }
        }

        public double CostPreTax
        {
            get { return _cost; }
            set
            {
                _cost = value;
                Notify( "CostPreTax" );
            }
        }

        public double Tax
        {
            get { return _tax; }
            set
            {
                _tax = value;
                Notify( "Tax" );
            }
        }

        public double TotalCost
        {
            get { return _totalCost; }
            set
            {
                _totalCost = value;
                UnsavedChanges = true;
                Notify( "TotalCost" );
            }
        }

    #endregion (Properties)


        public Order()
        {
            BeginMonitorEvents();
            DateTimeOrderPlaced = DateTime.Now;
        }


        internal void BeginMonitorEvents()
        {
            // Update billing info. on additions or removal of any order items
            OrderItems.CollectionChanged += OrderItems_CollectionChanged;

            // Set 'dirty' flag on change to any of customer's internal properties
            Customer.PropertyChanged += ContainedElementPropertyChanged;
            Customer.Address.PropertyChanged += ContainedElementPropertyChanged;
        }


        void ContainedElementPropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            if( UnsavedChanges != true )
                UnsavedChanges = true;
        }

        
        public Order Clone()
        {
            // Perform a shallow copy of all value fields...
            Order copy = (Order)MemberwiseClone();

            // Then, make deep copies of any reference fields...

            copy.Customer = Customer.Clone();

            copy.OrderItems = new ObservableCollection<Pizza>();
            copy.BeginMonitorEvents();

            foreach( Pizza pizza in OrderItems )
            {
                copy.OrderItems.Add( pizza.Clone() );
            }

            // Reset 'isDirty' flag
            copy.UnsavedChanges = false;

            return copy;
        }


        private void Notify( string strNotification )
        {
            if( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( strNotification ) );
            }
        }


        void OrderItems_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
        {
            CostPreTax = 0;

            foreach( Pizza pizza in OrderItems )
            {
                CostPreTax += pizza.Cost;
            }

            Tax = CostPreTax * _taxRate;

            TotalCost = CostPreTax + Tax;
        }


        public void UpdateProcessingTime()
        {
            ElapsedTime = ( DateTime.Now - DateTimeOrderPlaced );
        }
    }
}
